﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using FoundationLib.Ifc.Logging;

namespace FoundationLib.Logging
{
	/// <summary>
	/// Provides a default implementation of a technical logger.
	/// </summary>
	public class DefaultTechnicalLogger : TechnicalLogger
	{
		/// <summary>
		/// Creates a new <see cref="DefaultTechnicalLogger"/> instance.
		/// </summary>
		public DefaultTechnicalLogger()
			: base()
		{
		}

		private LogEntry CreateEntry(object message, TraceEventType type)
		{
			LogEntry entry = new LogEntry();
			entry.Message = message != null ? message.ToString() : "Unknown";
			entry.Severity = type;
			if (this.Configuration != null && !String.IsNullOrWhiteSpace(this.Configuration.Category))
				entry.Categories.Add(this.Configuration.Category);
			return entry;
		}

		private LogEntry CreateEntry(object message, TraceEventType type, Exception ex)
		{
			LogEntry entry = this.CreateEntry(message, type);
			entry.Message += Environment.NewLine + Environment.NewLine + ex.ToString();
			return entry;
		}

		private void WriteEntry(LogEntry entry)
		{
			Contract.Requires(entry != null);
			if (Logger.IsLoggingEnabled())
			{
				LogWriter writer = Logger.Writer;
				writer.Write(entry);
			}
		}

		/// <see cref="TechnicalLogger.Debug(object)"/>
		public override void Debug(object message)
		{
			this.WriteEntry(this.CreateEntry(message, TraceEventType.Verbose));
		}

		/// <see cref="TechnicalLogger.Debug(object, Exception)"/>
		public override void Debug(object message, Exception exception)
		{
			this.WriteEntry(this.CreateEntry(message, TraceEventType.Verbose, exception));
		}

		/// <see cref="TechnicalLogger.DebugFormat(string, object[])"/>
		public override void DebugFormat(string format, params object[] args)
		{
			this.WriteEntry(this.CreateEntry(String.Format(format, args), TraceEventType.Verbose));
		}

		/// <see cref="TechnicalLogger.Error(object)"/>
		public override void Error(object message)
		{
			this.WriteEntry(this.CreateEntry(message, TraceEventType.Error));
		}

		/// <see cref="TechnicalLogger.Error(object, Exception)"/>
		public override void Error(object message, Exception exception)
		{
			this.WriteEntry(this.CreateEntry(message, TraceEventType.Error, exception));
		}

		/// <see cref="TechnicalLogger.ErrorFormat(string, object[])"/>
		public override void ErrorFormat(string format, params object[] args)
		{
			this.WriteEntry(this.CreateEntry(String.Format(format, args), TraceEventType.Error));
		}

		/// <see cref="TechnicalLogger.Fatal(object)"/>
		public override void Fatal(object message)
		{
			this.WriteEntry(this.CreateEntry(message, TraceEventType.Critical));
		}

		/// <see cref="TechnicalLogger.Fatal(object, Exception)"/>
		public override void Fatal(object message, Exception exception)
		{
			this.WriteEntry(this.CreateEntry(message, TraceEventType.Critical, exception));
		}

		/// <see cref="TechnicalLogger.FatalFormat(string, object[])"/>
		public override void FatalFormat(string format, params object[] args)
		{
			this.WriteEntry(this.CreateEntry(String.Format(format, args), TraceEventType.Critical));
		}

		/// <see cref="TechnicalLogger.Info(object)"/>
		public override void Info(object message)
		{
			this.WriteEntry(this.CreateEntry(message, TraceEventType.Information));
		}

		/// <see cref="TechnicalLogger.Info(object, Exception)"/>
		public override void Info(object message, Exception exception)
		{
			this.WriteEntry(this.CreateEntry(message, TraceEventType.Information, exception));
		}

		/// <see cref="TechnicalLogger.InfoFormat(string, object[])"/>
		public override void InfoFormat(string format, params object[] args)
		{
			this.WriteEntry(this.CreateEntry(String.Format(format, args), TraceEventType.Information));
		}

		/// <see cref="TechnicalLogger.Warn(object)"/>
		public override void Warn(object message)
		{
			this.WriteEntry(this.CreateEntry(message, TraceEventType.Warning));
		}

		/// <see cref="TechnicalLogger.Warn(object, Exception)"/>
		public override void Warn(object message, Exception exception)
		{
			this.WriteEntry(this.CreateEntry(message, TraceEventType.Warning, exception));
		}

		/// <see cref="TechnicalLogger.WarnFormat(string, object[])"/>
		public override void WarnFormat(string format, params object[] args)
		{
			this.WriteEntry(this.CreateEntry(String.Format(format, args), TraceEventType.Warning));
		}
	}
}
